home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume17 / calentool / part17 < prev    next >
Encoding:
Internet Message Format  |  1991-04-07  |  54.3 KB

  1. From: billr@saab.CNA.TEK.COM (Bill Randle)
  2. Newsgroups: comp.sources.misc
  3. Subject: v17i098:  calentool - day/week/month/year-at-a-glance SunView tool, Part17/23
  4. Message-ID: <1991Apr7.005400.27751@sparky.IMD.Sterling.COM>
  5. Date: 7 Apr 91 00:54:00 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 8e51b884 ac278476 fe6ad68c 194a5f20
  8.  
  9. Submitted-by: Bill Randle <billr@saab.CNA.TEK.COM>
  10. Posting-number: Volume 17, Issue 98
  11. Archive-name: calentool/part17
  12.  
  13. #! /bin/sh
  14. # This is a shell archive.  Remove anything before this line, then unpack
  15. # it by saving it into a file and typing "sh file".  To overwrite existing
  16. # files, type "sh file -c".  You can also feed this as standard input via
  17. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  18. # will see the following message at the end:
  19. #        "End of archive 17 (of 23)."
  20. # Contents:  calentool.c common.c
  21. # Wrapped by billr@saab on Thu Mar 28 08:38:28 1991
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. if test -f 'calentool.c' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'calentool.c'\"
  25. else
  26. echo shar: Extracting \"'calentool.c'\" \(22129 characters\)
  27. sed "s/^X//" >'calentool.c' <<'END_OF_FILE'
  28. X/*
  29. X * $Header: calentool.c,v 2.5 91/03/27 16:44:59 billr Exp $
  30. X */
  31. X/*
  32. X * calentool.c
  33. X *
  34. X * calentool - a year/month/week/day-at-a-glance calendar for Sun workstations.
  35. X *
  36. X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com>
  37. X *
  38. X * Original source Copyright (C) 1987, Sun Microsystems, Inc.
  39. X *    All Rights Reserved
  40. X * Permission is hereby granted to use and modify this program in source
  41. X * or binary form as long as it is not sold for profit and this copyright
  42. X * notice remains intact.
  43. X *
  44. X *
  45. X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
  46. X *
  47. X * Changes and additions Copyright (C) 1988, 1989, 1991 Tektronix, Inc.
  48. X *    All Rights Reserved
  49. X * Permission is hereby granted to use and modify the modifications in source
  50. X * or binary form as long as they are not sold for profit and this copyright
  51. X * notice remains intact.
  52. X */
  53. X#include <stdio.h>
  54. X#include <suntool/sunview.h>
  55. X#include <suntool/panel.h>
  56. X#include <suntool/seln.h>
  57. X#include <sys/time.h>
  58. X#include <sys/file.h>
  59. X#include <signal.h>
  60. X#include "ct.h"
  61. X
  62. Xextern Pixfont *font, *sfont;
  63. Xextern char apts_pathname[], tmpapts_pathname[];
  64. Xextern char clockstr[];
  65. Xextern char *smonthnames[];
  66. Xextern Panel_item clock_pi;
  67. Xextern Frame fframe;
  68. Xextern Panel panel;
  69. Xextern int day_is_open;
  70. X#ifndef NO_SUN_MOON
  71. Xextern Frame sframe;
  72. X#endif
  73. X
  74. XFrame frame = 0;
  75. XPixwin *main_pixwin;
  76. Xstruct tm today, current;
  77. Xstruct tm First, Last;
  78. Xstruct tm olddate, closedate;
  79. Xint mainsw_state, selected_type;
  80. Xint x_coord, y_coord, startx, starty;
  81. Xint read_only;
  82. Xint nr_weekdays, dayslot_width, day_message_size, n_tslots, n_slots;
  83. Xint week_message_size, weekslot_width, weekslot_height, dayslot_height;
  84. Xint ybox_height, ybox_width;
  85. Xstruct dayslot *slots;
  86. Xstruct rect_limits boxlims[31];
  87. Xstruct rect_limits mboxlims[12];
  88. Xstruct week_arrow week_arrows[6];
  89. Xstruct weekrect week_boxes[7];
  90. XPixrect *ic_pr, *rev_ic_pr, *na_ic_pr;
  91. XRect *closed_rect;
  92. XRect ilabel_rect = {1, 67, 62, 9}; /* location of timestring under icon */
  93. Xchar *mailto = NULL;
  94. Xint one_based = 0, new_entry = 0, version2 = 0;
  95. Xint otherfile = 0;
  96. Xchar *othername;
  97. Xint beep = 0, show_time = 0, beep_open = 0;
  98. Xint include_old = 0, save_old = 0;
  99. X#ifndef NO_HOLIDAYS
  100. Xint holiday_a = 0, holiday_c = 0, holiday_i = 0;
  101. Xint holiday_j = 0, holiday_s = 0;
  102. X#endif
  103. Xchar *progname;
  104. Xstruct itimerval cal_timer;
  105. Xint update_interval = 0;
  106. Xint show_future = 1;
  107. XIcon icon, rev_icon, na_icon;
  108. XCursor year_cursor, month_cursor, week_cursor, day_cursor;
  109. XCursor wait_cursor;
  110. Xchar orig_apts_pathname[160];
  111. Xint orig_ro;
  112. Xchar timestr[16], datestr_day[3];
  113. Xstruct pr_prpos where;
  114. Xint working_msg;
  115. Xint hour24, monday_first, day_first;
  116. Xint expire_days = 0;
  117. Xint start_hour, end_hour, num_notes;
  118. Xint print_dev = PR_DEFAULT;
  119. Xint user_font = 0;
  120. Xint appt_check_limit, week_ofs = 0;
  121. Xint locked = 0;
  122. XSeln_client s_client;
  123. X
  124. Xstatic short icon_data[] = {
  125. X#include "std.icon"
  126. X};
  127. Xstatic short rev_icon_data[] = {
  128. X#include "rev.icon"
  129. X};
  130. Xstatic short na_icon_data[] = {
  131. X#include "nap.icon"
  132. X};
  133. Xmpr_static(ic_mpr, 64, 64, 1, icon_data);
  134. Xmpr_static(rev_ic_mpr, 64, 64, 1, rev_icon_data);
  135. Xmpr_static(na_ic_mpr, 64, 64, 1, na_icon_data);
  136. X
  137. Xstatic short year_cursor_data[] = {
  138. X#include "year.cursor"
  139. X};
  140. Xstatic short month_cursor_data[] = {
  141. X#include "month.cursor"
  142. X};
  143. Xstatic short week_cursor_data[] = {
  144. X#include "week.cursor"
  145. X};
  146. Xstatic short day_cursor_data[] = { 
  147. X#include "day.cursor"
  148. X};
  149. Xstatic short wait_cursor_data[] = {
  150. X#include <images/hglass.cursor>
  151. X};
  152. Xmpr_static(year_cursor_pr, 16, 16, 1, year_cursor_data);
  153. Xmpr_static(month_cursor_pr, 16, 16, 1, month_cursor_data);
  154. Xmpr_static(week_cursor_pr, 16, 16, 1, week_cursor_data);
  155. Xmpr_static(day_cursor_pr, 16, 16, 1, day_cursor_data);
  156. Xmpr_static(wait_cursor_pr, 16, 16, 1, wait_cursor_data);
  157. X
  158. X#ifndef NO_SUN_MOON
  159. Xstatic short moon_icon_data[] = {
  160. X#include "moony.icon"
  161. X};
  162. Xstatic short sun_icon_data[] = {
  163. X#include "sunny.icon"
  164. X};
  165. Xmpr_static(moon_icon_pr, 64, 64, 1, moon_icon_data);
  166. Xmpr_static(sun_icon_pr, 64, 64, 1, sun_icon_data);
  167. X#endif
  168. X
  169. Xstatic short tri_up_data[] = {
  170. X#include <images/tri_up.pr>
  171. X};
  172. Xmpr_static(tri_up_pr, 16, 16, 1, tri_up_data);
  173. X
  174. Xstatic short tri_right_data[] = {
  175. X#include <images/tri_right.pr>
  176. X};
  177. Xmpr_static(tri_right_pr, 16, 16, 1, tri_right_data);
  178. X
  179. Xchar *strcpy(), *strcat(), *rindex();
  180. Xstatic Notify_value itimer_handler();
  181. XNotify_value leave();
  182. XNotify_value myframe_interposer();
  183. Xvoid sel_func_key_proc();
  184. XSeln_result sel_reply_proc();
  185. X
  186. Xmain(argc,argv)
  187. Xint argc;
  188. Xchar *argv[];
  189. X{
  190. X    int   flag, i;
  191. X    int   printit = 0, toolrunning = 1, user_pos = 0;
  192. X    int   printit_dst = 0, limitcheck = -1;
  193. X    extern char *optarg;
  194. X    
  195. X    if (progname = rindex(*argv, '/'))
  196. X        progname++;
  197. X    else
  198. X        progname = *argv;
  199. X
  200. X    /*
  201. X     * setup defaults which might be changed by command
  202. X     * line options
  203. X     */
  204. X    nr_weekdays = NR_WEEKDAYS;
  205. X    monday_first = MON_FIRST;
  206. X    day_first = DAY_FIRST;
  207. X    hour24 = HOUR_24;
  208. X    start_hour = START_HOUR;
  209. X    end_hour = END_HOUR;
  210. X    num_notes = N_NOTESLOTS;
  211. X
  212. X    get_today();    /* initial day is today */
  213. X    current = today;
  214. X    read_only = 0;
  215. X    working_msg = 0;
  216. X
  217. X    /*
  218. X     * Check for -p, -P, -m or -M option, which means we don't want
  219. X     * to create the tool. Also check for -Wp and -Wi so we can supply
  220. X     * a resonable default if the user doesn't supply one.
  221. X     */
  222. X    i = argc;
  223. X    while (--i > 0) {
  224. X        if (!strncmp(argv[i], "-p", 2) || !strncmp(argv[i], "-m", 2)
  225. X            || !strncmp(argv[i], "-P", 2) || !strncmp(argv[i], "-M", 2)) {
  226. X            /* standard getopt doesn't allow optional
  227. X             * arguments, so we do a check here for
  228. X             * obsolete usage of the -p option
  229. X             */
  230. X            if ((argv[i][1] == 'p' || argv[i][1] == 'P') &&
  231. X                argv[i][2] == '\0') {
  232. X                fprintf(stderr, "calentool: -p/-P requires a 'd', 'w' or 'm' argument\n");
  233. X                exit(1);
  234. X            }
  235. X            toolrunning = 0;
  236. X        } else if (!strcmp(argv[i], "-Wp"))
  237. X            user_pos = 1;
  238. X        else if (!strcmp(argv[i], "-Wt"))
  239. X            user_font = 1;
  240. X    }
  241. X    if (toolrunning) {
  242. X        /* 
  243. X        ** Parse args: window_create must be called before getopt, so
  244. X        ** it can interpret and extract -W flags for SunView.
  245. X        */
  246. X        frame = window_create(NULL, FRAME,
  247. X                FRAME_ARGC_PTR_ARGV, &argc, argv,
  248. X                WIN_ERROR_MSG,
  249. X                "Can't create base frame. Are you in Suntools?",
  250. X                0);
  251. X        if ((s_client = seln_create(sel_func_key_proc, sel_reply_proc, NULL)) == NULL)
  252. X            err_rpt("Can't create selection svc client", NON_FATAL);
  253. X    }
  254. X
  255. X    while ((flag = getopt(argc, argv, "1:2:567bBd:eEf:il:m:M:op:P:rtu:zH:h:wx:T:s:S:N:")) != EOF)
  256. X        switch (flag) {   
  257. X            case 'f':    /* use this file */
  258. X            otherfile = 1;
  259. X            othername = optarg;
  260. X            break;
  261. X            
  262. X            case 'd':    /* starting date */
  263. X            (void)parse_date(optarg, TRUE);
  264. X            break;
  265. X
  266. X            case 'r':    /* read only file */
  267. X            read_only = 1;
  268. X            break;
  269. X            
  270. X            case '1':    /* -12 -- 12 hour time */
  271. X            if (*optarg == '2')
  272. X                hour24 = FALSE;
  273. X            break;
  274. X
  275. X            case '2':    /* -24 -- 24 hour time */
  276. X            if (*optarg == '4')
  277. X                hour24 = TRUE;
  278. X            break;
  279. X
  280. X            case 'e':    /* European calendar Mon-Sun */
  281. X            monday_first = TRUE;
  282. X            break;
  283. X
  284. X            case 'E':    /* European style */
  285. X            monday_first = TRUE;
  286. X            hour24 = TRUE;
  287. X            day_first = TRUE;
  288. X            break;
  289. X
  290. X            case 'p':    /* print and exit */
  291. X            read_only = 1;
  292. X            switch (*optarg) {
  293. X                case 'd':
  294. X                case 'D':
  295. X                    printit = PRI_DAY;
  296. X                    break;
  297. X                case 'w':
  298. X                    printit = PRI_WEEK;
  299. X                    week_ofs = 0;
  300. X                    break;
  301. X                case 'W':
  302. X                    printit = PRI_WEEK;
  303. X                    week_ofs = 1;
  304. X                    break;
  305. X                case 'm':
  306. X                case 'M':
  307. X                    printit = PRI_MONTH;
  308. X                    break;
  309. X                default:
  310. X                    fprintf(stderr, "calentool: unknown print option.", NON_FATAL);
  311. X                    break;
  312. X            }
  313. X            if (!printit_dst)
  314. X                printit_dst = DST_STDOUT;
  315. X            break;
  316. X
  317. X            case 'P':    /* print and exit (ignore some notes) */
  318. X            read_only = 1;
  319. X            switch (*optarg) {
  320. X                case 'd':
  321. X                case 'D':
  322. X                    printit = PRI_DAY_XNOTES;
  323. X                    break;
  324. X                case 'w':
  325. X                    printit = PRI_WEEK_XNOTES;
  326. X                    week_ofs = 0;
  327. X                    break;
  328. X                case 'W':
  329. X                    printit = PRI_WEEK_XNOTES;
  330. X                    week_ofs = 1;
  331. X                    break;
  332. X                case 'm':
  333. X                case 'M':
  334. X                    printit = PRI_MONTH_XNOTES;
  335. X                    break;
  336. X                default:
  337. X                    fprintf(stderr, "calentool: unknown print option.", NON_FATAL);
  338. X                    break;
  339. X            }
  340. X            if (!printit_dst)
  341. X                printit_dst = DST_STDOUT;
  342. X            break;
  343. X
  344. X            case 'l':    /* appt check limit */
  345. X            if (optarg)
  346. X                limitcheck = atoi(optarg);
  347. X            else
  348. X                limitcheck = 0;
  349. X            break;
  350. X
  351. X            case 'm':    /* mail today's appts and exit */
  352. X            read_only = 1;
  353. X            if (!printit)
  354. X                printit = PRI_DAY;
  355. X            printit_dst = DST_MAIL;
  356. X            mailto = optarg;
  357. X            break;
  358. X
  359. X            case 'M':    /* mail today's appts and exit (ignore
  360. X                   some notes) */
  361. X            read_only = 1;
  362. X            if (!printit)
  363. X                printit = PRI_DAY_XNOTES;
  364. X            printit_dst = DST_MAIL;
  365. X            mailto = optarg;
  366. X            break;
  367. X
  368. X            case 'b':    /* beep to console for pending appt */
  369. X            beep = 1;
  370. X            break;
  371. X
  372. X            case 'B':    /* beep then open wondow */
  373. X            beep_open = 1;
  374. X            break;
  375. X
  376. X            case 'i':    /* include old appt files */
  377. X            include_old = 1;
  378. X            break;
  379. X
  380. X            case 'o':    /* save outdated appts to another file */
  381. X            save_old = 1;
  382. X            break;
  383. X
  384. X            case 't':    /* display current time under icon */
  385. X            show_time = 1;
  386. X            break;
  387. X
  388. X            case '5':    /* Mon - Fri week display */
  389. X            nr_weekdays = 5;
  390. X            break;
  391. X
  392. X            case '6':    /* Mon - Sat week display */
  393. X            nr_weekdays = 6;
  394. X            break;
  395. X
  396. X            case '7':    /* Sun - Sat (or Mon-Sun) week display */
  397. X            nr_weekdays = 7;
  398. X            break;
  399. X
  400. X            case 'u':    /* update interval (in seconds) */
  401. X            update_interval = atoi(optarg);
  402. X            break;
  403. X
  404. X            case 'w':    /* display Working! message */
  405. X            working_msg = 1;
  406. X            break;
  407. X
  408. X            case 'x':    /* eXpire appts after so many days */
  409. X            expire_days = atoi(optarg);
  410. X            break;
  411. X
  412. X            case 'z':    /* zero offset -- new style appts file */
  413. X            one_based = 1;
  414. X            break;
  415. X
  416. X#ifndef NO_HOLIDAYS
  417. X            case 'h':
  418. X            /* show certain holidays */
  419. X            switch (*optarg) {
  420. X                case 'A':
  421. X                    /* all holidays */
  422. X                    holiday_a = holiday_c = holiday_i = 1;
  423. X                    holiday_j = holiday_s = 1;
  424. X                    break;
  425. X                case 'a':
  426. X                    /* astronomical events */
  427. X                    holiday_a = 1;
  428. X                    break;
  429. X                case 'c':
  430. X                    /* Christian holidays */
  431. X                    holiday_c = 1;
  432. X                    break;
  433. X                case 'i':
  434. X                    /* Islamic holidays */
  435. X                    holiday_i = 1;
  436. X                    break;
  437. X                case 'j':
  438. X                    /* Jewish holidays */
  439. X                    holiday_j = 1;
  440. X                    break;
  441. X                case 's':
  442. X                    /* secular holidays */
  443. X                    holiday_s = 1;
  444. X                    break;
  445. X                default:
  446. X                    fprintf(stderr, "calentool: unknown holiday option (must be one of \"Aacijs\")");
  447. X                    break;
  448. X            }
  449. X            break;
  450. X
  451. X            case 'H':
  452. X            /* show certain holidays day/week display only */
  453. X            switch (*optarg) {
  454. X                case 'A':
  455. X                    /* all holidays */
  456. X                    holiday_a = holiday_c = holiday_i = 2;
  457. X                    holiday_j = holiday_s = 2;
  458. X                    break;
  459. X                case 'a':
  460. X                    /* astronomical events */
  461. X                    holiday_a = 2;
  462. X                    break;
  463. X                case 'c':
  464. X                    /* Christian holidays */
  465. X                    holiday_c = 2;
  466. X                    break;
  467. X                case 'i':
  468. X                    /* Islamic holidays */
  469. X                    holiday_i = 2;
  470. X                    break;
  471. X                case 'j':
  472. X                    /* Jewish holidays */
  473. X                    holiday_j = 2;
  474. X                    break;
  475. X                case 's':
  476. X                    /* secular holidays */
  477. X                    holiday_s = 2;
  478. X                    break;
  479. X                default:
  480. X                    fprintf(stderr, "calentool: unknown holiday option (must be one of \"Aacijs\")");
  481. X                    break;
  482. X            }
  483. X            break;
  484. X#else
  485. X            case 'h':
  486. X            case 'H':
  487. X                fprintf(stderr, "calentool: -h and -H options not available\n");
  488. X                break;
  489. X#endif
  490. X            case 'T':
  491. X            if (!strncmp(optarg, "ps", 2))
  492. X                print_dev = PR_POSTSCRIPT;
  493. X            else
  494. X                print_dev = PR_ASCII;
  495. X            break;
  496. X
  497. X            case 's':    /* start hour */
  498. X            start_hour = atoi(optarg);
  499. X            if (start_hour < 0 || start_hour > 23)
  500. X                fprintf(stderr, "calentool: start hour must be in the range 0 - 23\n");
  501. X            break;
  502. X
  503. X            case 'S':    /* Stop (end) hour */
  504. X            end_hour = atoi(optarg);
  505. X            if (end_hour < 1 || end_hour > 24)
  506. X                fprintf(stderr, "calentool: end hour must be in the range 1 - 24\n");
  507. X            break;
  508. X
  509. X            case 'N':    /* number of note slots */
  510. X            num_notes = atoi(optarg);
  511. X            break;
  512. X
  513. X            case '?':
  514. X            default:
  515. X            fprintf(stderr, "usage: %s [options...]\nwhere <options> are:\n", progname);
  516. X            fprintf(stderr, " -f <appointment_file>\n");
  517. X            fprintf(stderr, " -r        // readonly\n");
  518. X            fprintf(stderr, " -p <dwWm>    // print selected day [d], week [w] or month [m] appts and exit\n");
  519. X            fprintf(stderr, " -P <dwWm>    // like -p, only don't print marked notes\n");
  520. X            fprintf(stderr, " -m <user>    // mail selected days appts to <user>\n");
  521. X            fprintf(stderr, " -M <user>    // like -m, only don't mail marked notes\n");
  522. X            fprintf(stderr, " [-5|-6|-7]    // 5, 6 or 7-day week display\n");
  523. X            fprintf(stderr, " [-12|-24]    // 12 or 24 hour time format\n");
  524. X            fprintf(stderr, " -d <date>    // display appts for <date>\n");
  525. X            fprintf(stderr, " -b        // beep and display message when appt is pending\n");
  526. X            fprintf(stderr, " -B        // beep and open window when appt is pending\n");
  527. X            fprintf(stderr, " -i        // auto-include outdated appts files\n");
  528. X            fprintf(stderr, " -l [0|1]    // set limit check for appts to include notes\n");
  529. X            fprintf(stderr, " -o        // create outdated include files\n");
  530. X            fprintf(stderr, " -t        // display time below icon\n");
  531. X            fprintf(stderr, " -u <interval>    // time update interval (seconds)\n");
  532. X            fprintf(stderr, " -w        // display 'Working!' message\n");
  533. X            fprintf(stderr, " -e        // Mon-Sun week display\n");
  534. X            fprintf(stderr, " -E        // European options (-e, -24)\n");
  535. X#ifndef NO_HOLIDAYS
  536. X            fprintf(stderr, " -h <Aacijs>    // display selected computed holidays\n");
  537. X            fprintf(stderr, "        // A=All, a=astronomical, c=Christian,\n");
  538. X            fprintf(stderr, "        // i=Islamic, j=Jewish, s=secular\n");
  539. X            fprintf(stderr, " -H <Aacijs>    // like -h, only flag them as marked\n");
  540. X#endif
  541. X            fprintf(stderr, " -T <printdev>    // printer output type for -p and -m options\n");
  542. X            fprintf(stderr, " -s <hour>    // start hour\n");
  543. X            fprintf(stderr, " -S <hour>    // stop hour\n");
  544. X            fprintf(stderr, " -N <num>    // number of note slots\n");
  545. X            fprintf(stderr, " -x <days>    // expire appts after <days> days\n");
  546. X            fprintf(stderr, " -z        // conversion flag (see INSTALL)\n");
  547. X            fprintf(stderr, " <window_opts>    // Suntools -W options\n");
  548. X            exit(1);
  549. X            break;
  550. X        }
  551. X
  552. X    if (toolrunning) {
  553. X        (void) notify_set_signal_func(frame, leave, SIGHUP, NOTIFY_ASYNC);
  554. X        (void) notify_set_signal_func(frame, leave, SIGINT, NOTIFY_ASYNC);
  555. X        (void) notify_set_signal_func(frame, leave, SIGTERM, NOTIFY_ASYNC);
  556. X    }
  557. X
  558. X    /* set default printer to something useful */
  559. X    if (print_dev == PR_DEFAULT) {
  560. X        if (printit == PRI_MONTH || printit == PRI_MONTH_XNOTES)
  561. X            print_dev = PR_POSTSCRIPT;
  562. X        else
  563. X            print_dev = PR_ASCII;
  564. X    }
  565. X    /*
  566. X    ** setup number of slots and allocate memory for them
  567. X    */
  568. X    if ( start_hour >= end_hour )
  569. X        err_rpt("Start Hour must be less than Stop Hour", FATAL);
  570. X    n_tslots = (end_hour - start_hour) * 2;
  571. X    n_slots = n_tslots + num_notes;
  572. X    appt_check_limit = APPT_CHECK_LIMIT;  /* set default */
  573. X    if (limitcheck == 0)
  574. X        appt_check_limit = n_tslots;
  575. X    else if (limitcheck == 1)
  576. X        appt_check_limit = n_slots;
  577. X    /* make room for n_slots dayslot entries and week entries */
  578. X    if ((slots = (struct dayslot *)malloc(n_slots* sizeof(struct dayslot))) == NULL)
  579. X        err_rpt("Can't get enough storage for day slots", FATAL);
  580. X    for (i=0; i<nr_weekdays; i++)
  581. X        if ((week_boxes[i].weekslots = 
  582. X            (struct dayslot *)malloc(n_slots*sizeof(struct dayslot))) == NULL)
  583. X            err_rpt("Can't get enough storage for week slots", FATAL);
  584. X
  585. X    /* 
  586. X    ** Find the calendar file, etc.
  587. X    */
  588. X    if (do_files(FALSE))
  589. X        /* can't open (or create) appts file */
  590. X        exit(1);
  591. X    strcpy(orig_apts_pathname, apts_pathname);
  592. X    orig_ro = read_only;
  593. X    get_printer();
  594. X    
  595. X    if (printit) {
  596. X        print_apts(printit, printit_dst);
  597. X        if (save_old || expire_days) {
  598. X            read_only = 0;  /* allow updates */
  599. X            expire(expire_days);
  600. X        }
  601. X        exit(0);
  602. X    }
  603. X
  604. X    get_fonts();
  605. X
  606. X    if (!update_interval) {
  607. X        if (!strcmp(UPDATE_RATE, "minute"))
  608. X            update_interval = 60;
  609. X        else if (!strcmp(UPDATE_RATE, "second"))
  610. X            update_interval = 1; /* check in 1 sec */
  611. X        else {
  612. X            err_rpt("unknown update interval, defaulting to seconds", NON_FATAL);
  613. X            update_interval = 1; /* check in 1 sec */
  614. X        }
  615. X    }
  616. X
  617. X    /* create the cursors */
  618. X    year_cursor = cursor_create(CURSOR_IMAGE, &year_cursor_pr,
  619. X            CURSOR_XHOT, 7, CURSOR_YHOT, 7,
  620. X            CURSOR_OP, PIX_SRC^PIX_DST,
  621. X            0);
  622. X    month_cursor = cursor_create(CURSOR_IMAGE, &month_cursor_pr,
  623. X            CURSOR_XHOT, 7, CURSOR_YHOT, 7,
  624. X            CURSOR_OP, PIX_SRC^PIX_DST,
  625. X            0);
  626. X    week_cursor = cursor_create(CURSOR_IMAGE, &week_cursor_pr,
  627. X            CURSOR_XHOT, 7, CURSOR_YHOT, 7,
  628. X            CURSOR_OP, PIX_SRC^PIX_DST,
  629. X            0);
  630. X    day_cursor = cursor_create(CURSOR_IMAGE, &day_cursor_pr,
  631. X            CURSOR_XHOT, 7, CURSOR_YHOT, 7,
  632. X            CURSOR_OP, PIX_SRC^PIX_DST,
  633. X            0);
  634. X    wait_cursor = cursor_create(CURSOR_IMAGE, &wait_cursor_pr,
  635. X            CURSOR_XHOT, 7, CURSOR_YHOT, 7,
  636. X            CURSOR_OP, PIX_SRC^PIX_DST,
  637. X            0);
  638. X
  639. X    /* create the icons */
  640. X    icon = icon_create(0);
  641. X    rev_icon = icon_create(0);
  642. X    na_icon = icon_create(0);
  643. X    /*
  644. X     * make the icon big enough to display the time
  645. X     * underneath the base icon image if -t option
  646. X     */
  647. X    ic_pr = mem_create(64, (show_time ? 77 : 64), 1);
  648. X    rev_ic_pr = mem_create(64, (show_time ? 77 : 64), 1);
  649. X    na_ic_pr = mem_create(64, (show_time ? 77 : 64), 1);
  650. X    sprintf(datestr_day, "%2d", today.tm_mday);
  651. X    /* the basic standard icon */
  652. X    pr_rop(ic_pr, 0, 0, 64, 64, PIX_SRC, &ic_mpr, 0, 0);
  653. X    if (show_time) {
  654. X        /* time string displayed below icon */
  655. X        format_icon_time();
  656. X        if (update_interval >= 60) {
  657. X            /* no seconds displayed, adjust label position */
  658. X            ilabel_rect.r_left += 2*sfont->pf_defaultsize.x - 2;
  659. X            ilabel_rect.r_width -= 2*sfont->pf_defaultsize.x;
  660. X        }
  661. X        if (!hour24) {
  662. X            /* am/pm, increase size of label rect */
  663. X            ilabel_rect.r_left -= sfont->pf_defaultsize.x;
  664. X            ilabel_rect.r_width += sfont->pf_defaultsize.x;
  665. X        }
  666. X        /* draw a box around the time appendage */
  667. X        pr_vector(ic_pr, 0, 64, 63, 64, PIX_SET, 1);
  668. X        pr_vector(ic_pr, 63, 64, 63, 76, PIX_SET, 1);
  669. X        pr_vector(ic_pr, 63, 76, 0, 76, PIX_SET, 1);
  670. X        pr_vector(ic_pr, 0, 76, 0, 64, PIX_SET, 1);
  671. X
  672. X        pr_rop(rev_ic_pr, 0, 0, 64, 77, PIX_SRC, ic_pr, 0, 0);
  673. X        pr_rop(rev_ic_pr, 0, 0, 64, 64, PIX_SRC, &rev_ic_mpr, 0, 0);
  674. X        pr_rop(na_ic_pr, 0, 0, 64, 77, PIX_SRC, ic_pr, 0, 0);
  675. X        pr_rop(na_ic_pr, 0, 0, 64, 64, PIX_SRC, &na_ic_mpr, 0, 0);
  676. X    } else {
  677. X        pr_rop(rev_ic_pr, 0, 0, 64, 64, PIX_SRC, &rev_ic_mpr, 0, 0);
  678. X        pr_rop(na_ic_pr, 0, 0, 64, 64, PIX_SRC, &na_ic_mpr, 0, 0);
  679. X    }
  680. X    /* add in the date */
  681. X    where.pr = ic_pr;
  682. X    where.pos.x = 13;
  683. X    where.pos.y = 49 + 5;
  684. X    pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_day);
  685. X    where.pr = na_ic_pr;
  686. X    pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_day);
  687. X    where.pr = rev_ic_pr;
  688. X    pf_ttext(where, PIX_SRC, sfont, datestr_day);
  689. X    where.pos.x = 39;
  690. X    where.pr = ic_pr;
  691. X    pf_ttext(where, PIX_NOT(PIX_SRC), sfont, smonthnames[today.tm_mon]);
  692. X    where.pr = na_ic_pr;
  693. X    pf_ttext(where, PIX_NOT(PIX_SRC), sfont, smonthnames[today.tm_mon]);
  694. X    where.pr = rev_ic_pr;
  695. X    pf_ttext(where, PIX_SRC, sfont, smonthnames[today.tm_mon]);
  696. X    (void)icon_init_from_pr(icon, ic_pr);
  697. X    (void)icon_init_from_pr(rev_icon, rev_ic_pr);
  698. X    (void)icon_init_from_pr(na_icon, na_ic_pr);
  699. X    if (show_time) {
  700. X        /* add label field */
  701. X        icon_set(icon, ICON_LABEL_RECT, &ilabel_rect,
  702. X                ICON_LABEL, timestr,
  703. X                ICON_FONT, sfont,
  704. X                0);
  705. X        icon_set(rev_icon, ICON_LABEL_RECT, &ilabel_rect,
  706. X                ICON_LABEL, timestr,
  707. X                ICON_FONT, sfont,
  708. X                0);
  709. X        icon_set(na_icon, ICON_LABEL_RECT, &ilabel_rect,
  710. X                ICON_LABEL, timestr,
  711. X                ICON_FONT, sfont,
  712. X                0);
  713. X    }
  714. X
  715. X    week_message_size = WEEK_MESSAGE_SIZE;
  716. X    weekslot_width = (font->pf_defaultsize.x * week_message_size) + 6;
  717. X    dayslot_width = (nr_weekdays - 1) * weekslot_width;
  718. X    day_message_size = dayslot_width / font->pf_defaultsize.x;
  719. X    ybox_height = dayslot_height = weekslot_height = font->pf_defaultsize.y + 6;
  720. X    ybox_width = 3 * font->pf_defaultsize.x;
  721. X
  722. X    init_pixrects();    /* Initialize pictures. */
  723. X
  724. X    /* Create the rest of the tool */
  725. X    if (user_pos)
  726. X        window_set(frame,
  727. X             WIN_WIDTH, (nr_weekdays+1)*weekslot_width+40,
  728. X             WIN_HEIGHT, (n_slots+5)*weekslot_height+72,
  729. X             FRAME_ICON, icon,
  730. X             0);
  731. X    else
  732. X        /* supply default position */
  733. X        window_set(frame,
  734. X             WIN_WIDTH, (nr_weekdays+1)*weekslot_width+40,
  735. X             WIN_HEIGHT, (n_slots+5)*weekslot_height+72,
  736. X             WIN_X, 100, WIN_Y, 56,
  737. X             FRAME_ICON, icon,
  738. X             0);
  739. X
  740. X    closed_rect = (Rect *)window_get(frame, FRAME_CLOSED_RECT);
  741. X    create_panel();
  742. X    create_main_window();
  743. X    create_attr_frame();    /* normally hidden */
  744. X    create_del_frame();    /* normally hidden */
  745. X    create_file_frame();    /* normally hidden */
  746. X    create_date_frame();    /* normally hidden */
  747. X#ifndef NO_PRINTER
  748. X    create_print_frame();    /* normally hidden */
  749. X#endif
  750. X    check_calendar();    /* set proper icon */
  751. X
  752. X    /* interpose on frame events (specifically open/close) */
  753. X    (void) notify_interpose_event_func(frame, myframe_interposer, NOTIFY_SAFE);
  754. X
  755. X    timerclear(&(cal_timer.it_interval));
  756. X    timerclear(&(cal_timer.it_value));
  757. X    cal_timer.it_value.tv_sec = (long)update_interval;
  758. X    cal_timer.it_value.tv_usec = 0L;
  759. X    (void) notify_set_itimer_func(frame, itimer_handler, ITIMER_REAL, &cal_timer, NULL);
  760. X
  761. X    window_main_loop(frame);
  762. X
  763. X    (void)leave();
  764. X}            
  765. X             
  766. X
  767. Xstatic Notify_value
  768. Xitimer_handler(me, which)
  769. XNotify_client me;
  770. Xint which;
  771. X{
  772. X    static int timeout_cntr = 0;
  773. X    Icon cur_icon;
  774. X
  775. X    timerclear(&(cal_timer.it_interval));
  776. X    timerclear(&(cal_timer.it_value));
  777. X    cal_timer.it_value.tv_sec = (long)update_interval;
  778. X    cal_timer.it_value.tv_usec = 0L;
  779. X    (void) notify_set_itimer_func(frame, itimer_handler, ITIMER_REAL, &cal_timer, NULL);
  780. X    get_today();
  781. X    /* update date/time displayed in the panel */
  782. X    panel_set(clock_pi, PANEL_LABEL_STRING, clockstr, 0);
  783. X    if (show_time && (int)window_get(frame, FRAME_CLOSED))
  784. X        update_icon_time();
  785. X#ifndef NO_SUN_MOON
  786. X    /* update data in Sun Data frame (if it's open) */
  787. X    if (sframe)
  788. X        write_times();
  789. X#endif
  790. X    /* only check appointments every TIME_OUT minutes */
  791. X    timeout_cntr += update_interval;
  792. X#undef TIME_OUT
  793. X#define TIME_OUT 1
  794. X    if (timeout_cntr/60 < TIME_OUT)
  795. X        return(NOTIFY_DONE);
  796. X    timeout_cntr = 0;
  797. X    /* check todays appointments */
  798. X    check_calendar();
  799. X    return(NOTIFY_DONE);
  800. X}
  801. X
  802. XNotify_value
  803. Xleave(me, signal, when)
  804. XNotify_client me;
  805. Xint signal;
  806. XNotify_signal_mode when;
  807. X{
  808. X    if (day_is_open)
  809. X        close_day();
  810. X
  811. X    /* create outdated include files (if necessary) */
  812. X    if (save_old || expire_days)
  813. X        expire(expire_days);
  814. X
  815. X    /* delete tmp file */
  816. X    if (access(tmpapts_pathname, R_OK) == 0 && unlink(tmpapts_pathname) < 0)
  817. X        perror(tmpapts_pathname);
  818. X
  819. X    seln_destroy(s_client);
  820. X    exit(0);
  821. X    /* NOTREACHED */
  822. X    return(NOTIFY_DONE);
  823. X}
  824. END_OF_FILE
  825. if test 22129 -ne `wc -c <'calentool.c'`; then
  826.     echo shar: \"'calentool.c'\" unpacked with wrong size!
  827. fi
  828. # end of 'calentool.c'
  829. fi
  830. if test -f 'common.c' -a "${1}" != "-c" ; then 
  831.   echo shar: Will not clobber existing file \"'common.c'\"
  832. else
  833. echo shar: Extracting \"'common.c'\" \(29124 characters\)
  834. sed "s/^X//" >'common.c' <<'END_OF_FILE'
  835. X/*
  836. X * $Header: common.c,v 1.2 91/03/27 16:45:05 billr Exp $
  837. X */
  838. X/*
  839. X * common.c
  840. X *
  841. X * Author: by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
  842. X *
  843. X * Copyright (C) 1988, 1989, 1991 Tektronix, Inc.
  844. X *    All Rights Reserved
  845. X * Permission is hereby granted to use and modify the modifications in source
  846. X * or binary form as long as they are not sold for profit and this copyright
  847. X * notice remains intact.
  848. X */
  849. X
  850. X#include <stdio.h>
  851. X#include <ctype.h>
  852. X#include <sys/time.h>
  853. X#include <sys/types.h>
  854. X#include <sys/stat.h>
  855. X#include <sys/file.h>
  856. X#ifndef CALENCHECK
  857. X# include <suntool/sunview.h>
  858. X# include <pwd.h>
  859. X#endif
  860. X#ifndef NO_DEFAULTS
  861. X# include <sunwindow/defaults.h>
  862. X#endif
  863. X#include "ct.h"
  864. X
  865. Xstruct tm save_day;
  866. Xstruct appt_entry future[MAX_FUTURE_ENTRIES];
  867. Xint findex = 0;         /* index into struct future array */;
  868. Xint day_is_open = 0;    /* indicates when slot info is current */
  869. Xchar apts_pathname[160], tmpapts_pathname[160];
  870. Xchar apts_dir[128], lib_dir[128];
  871. Xchar t_title[160];
  872. X
  873. Xextern struct tm current, today, First;
  874. Xextern struct dayslot *slots;
  875. Xextern char apts_pathname[], tmpapts_pathname[];
  876. Xextern char *progname;
  877. Xextern char *othername;
  878. Xextern int n_slots, n_tslots, read_only, new_entry;
  879. Xextern int otherfile, one_based, version2;
  880. Xextern int show_future, start_hour;
  881. Xextern int mainsw_state;
  882. X
  883. X#ifndef CALENCHECK
  884. Xextern struct tm olddate, closedate;
  885. Xextern Frame frame, prompt_frame;
  886. Xextern Icon icon, rev_icon, na_icon;
  887. Xextern char datestr_day[];
  888. Xextern struct pr_prpos where;
  889. Xextern Pixrect *ic_pr, *rev_ic_pr, *na_ic_pr;
  890. Xextern int beep, beep_open;
  891. Xextern int appt_check_limit;
  892. Xextern Pixfont *sfont;
  893. Xextern char *smonthnames[];
  894. Xextern char *mailto;
  895. Xextern int locked;
  896. Xextern char *version();
  897. X#endif
  898. X
  899. X#ifndef NO_HOLIDAYS
  900. Xextern int holiday_a, holiday_c, holiday_i, holiday_j, holiday_s;
  901. X
  902. Xextern int a_dates(), c_dates(), i_dates(), j_dates(), s_dates();
  903. Xextern struct appt_entry a_appts[], c_appts[];
  904. Xextern struct appt_entry i_appts[], j_appts[];
  905. Xextern struct appt_entry s_appts[];
  906. X#endif
  907. Xextern char *strcpy(), *strncpy(), *index();
  908. X
  909. X/*
  910. X * Add an appointment entry pointed to by aptr to the day slot
  911. X * specified by slotno. This routine is also used by paste()
  912. X * when copying an entry off the save shelf. If dpyflag is true,
  913. X * then any deactivated slots are cleared on the display (used by
  914. X * paste). Also used to add a deleted entry for a specific day.
  915. X */
  916. Xadd_to_slot(slotno, aptr, dpyflag)
  917. Xint slotno;
  918. Xstruct appt_entry *aptr;
  919. Xint dpyflag;
  920. X{
  921. X    struct appt_entry *nappt, *optr;
  922. X    int n_arrows, n, nbi, found = 0, i;
  923. X
  924. X    if ((nappt = (struct appt_entry *)malloc(sizeof(struct appt_entry))) == NULL)
  925. X        err_rpt("out of memory", FATAL);
  926. X    if (aptr == NULL) {
  927. X        /* fill in some needed fields */
  928. X        nappt->arrows = nappt->flags = 0;
  929. X        nappt->sindex = 0;
  930. X        nappt->str[0] = '\0';
  931. X    } else
  932. X        *nappt = *aptr;
  933. X    nappt->next = NULL;
  934. X    /* add appt to list of appts for this slot */
  935. X    if (slots[slotno].first == NULL) {
  936. X        slots[slotno].first = nappt;
  937. X        slots[slotno].cur_appt = nappt;
  938. X    } else {
  939. X        /* search for end of list */
  940. X        for (optr=slots[slotno].first;optr->next;optr=optr->next)
  941. X            ;
  942. X        optr->next = nappt;
  943. X    }
  944. X    /* make sure it doesn't extend too far and truncate if neccessary */
  945. X    if (slotno >= n_tslots)
  946. X        nappt->arrows = 0;    /* force notes to have no arrows */
  947. X    else if ((slotno + nappt->arrows) >= n_tslots)
  948. X        nappt->arrows = n_tslots - slotno - 1;    /* truncate */
  949. X    n_arrows = nappt->arrows;
  950. X    if (nappt->flags & DELETED) {
  951. X        /* look for matching non-deleted appt in list */
  952. X        for (optr=slots[slotno].first;optr && !found;optr=optr->next)
  953. X            if (!strcmp(nappt->str, optr->str)
  954. X                && !(optr->flags & DELETED)
  955. X                && Repeating(optr->flags)) {
  956. X                found = 1;
  957. X                break;
  958. X            }
  959. X        if (found && slots[slotno].cur_appt == optr) {
  960. X            /* the deleted appt is the current one */
  961. X            /* if it's active, undisplay it and display
  962. X             * next one in list (if any)
  963. X             */
  964. X            if (slots[slotno].active) {
  965. X                if (slots[slotno].active > 1)
  966. X                    /* there's another one here */
  967. X                    next_appt(slotno, dpyflag);
  968. X                else
  969. X                    deactivate_slot(slotno, dpyflag);
  970. X                /* adjust reference counts */
  971. X                slots[slotno].count--;
  972. X                slots[slotno].active--;
  973. X                i = 0;
  974. X                while (++i <= n_arrows)
  975. X                    --slots[slotno+i].count;
  976. X            } else {
  977. X                /* currently inactive */
  978. X                /* set current to next one in the list */
  979. X                if (optr->next)
  980. X                    slots[slotno].cur_appt = optr->next;
  981. X                else
  982. X                    slots[slotno].cur_appt = slots[slotno].first;
  983. X                /* adjust the counts */
  984. X                slots[slotno].active--;
  985. X                while (n_arrows >= 0)
  986. X                    slots[slotno+(n_arrows--)].count--;
  987. X            }
  988. X        } else {
  989. X            /* just adjust the counts */
  990. X            slots[slotno].active--;
  991. X            while (n_arrows >= 0)
  992. X                slots[slotno+(n_arrows--)].count--;
  993. X        }
  994. X    } else {
  995. X        /* look for matching deleted appt in list */
  996. X        if (Repeating(nappt->flags)) {
  997. X            for (optr=slots[slotno].first;optr && !found;optr=optr->next)
  998. X                if (!strcmp(nappt->str, optr->str) && optr->flags & DELETED) {
  999. X                    found = 1;
  1000. X                    break;
  1001. X                }
  1002. X            if (found) {
  1003. X                /* just adjust reference counts and return */
  1004. X                slots[slotno].active++;
  1005. X                while (n_arrows >= 0)
  1006. X                    slots[slotno+(n_arrows--)].count++;
  1007. X                return;
  1008. X            }
  1009. X        }
  1010. X        /*
  1011. X         * Make sure there are no overlaps with the appt we
  1012. X         * are adding. If there are, hide the overlapping appt.
  1013. X         */
  1014. X        if (slots[slotno].active)
  1015. X            deactivate_slot(slotno, dpyflag);
  1016. X        /* set current one to the new one */
  1017. X        slots[slotno].cur_appt = nappt;
  1018. X        /* now go back and put in the info for the appt we're inserting */
  1019. X        slots[slotno].count++;
  1020. X        slots[slotno].active++;
  1021. X        if (n_arrows > 0) {
  1022. X            slots[slotno+n_arrows].count++;
  1023. X            while (--n_arrows > 0)
  1024. X                slots[slotno+n_arrows].count++;
  1025. X        }
  1026. X    }
  1027. X    if (dpyflag)
  1028. X        draw_day_appts();    /* redraw display */
  1029. X}
  1030. X
  1031. X/* add a note to the current day */
  1032. Xadd_note(appt)
  1033. Xstruct appt_entry *appt;
  1034. X{
  1035. X    int    slotno, found = 0;
  1036. X    struct appt_entry *optr;
  1037. X
  1038. X    /* This used to just find a free slot and add the note
  1039. X     * to it. However, with deleted notes we need to find
  1040. X     * the matching slotno (if it exists) to make sure that
  1041. X     * the deleted and non-deleted notes end up in the same
  1042. X     * slot number (so they won't be displayed).
  1043. X     */
  1044. X    if (appt->flags & DELETED) {
  1045. X        /* look for matching non-deleted note */
  1046. X        for (slotno=n_tslots; slotno<n_slots && !found; slotno++) {
  1047. X            if (!slots[slotno].active)
  1048. X                break;    /* no more notes */
  1049. X            for (optr=slots[slotno].first;optr;optr=optr->next) {
  1050. X                if (!strcmp(appt->str, optr->str)
  1051. X                    && !(optr->flags & DELETED)
  1052. X                    && Repeating(optr->flags)) {
  1053. X                    found = 1;
  1054. X                    break;
  1055. X                }
  1056. X            }
  1057. X        }
  1058. X    } else {
  1059. X        /* look for free slot and/or matching deleted note */
  1060. X        for (slotno=n_tslots; slotno<n_slots && !found; slotno++) {
  1061. X            if (!slots[slotno].active)
  1062. X                break;    /* no more notes */
  1063. X            for (optr=slots[slotno].first;optr;optr=optr->next)
  1064. X                if (!strcmp(appt->str, optr->str)
  1065. X                    && (optr->flags & DELETED)
  1066. X                    && Repeating(appt->flags)) {
  1067. X                    found = 1;
  1068. X                    break;
  1069. X                }
  1070. X        }
  1071. X    }
  1072. X    if (found)
  1073. X        --slotno;  /* for loop incremented slotno */
  1074. X    if (slotno == n_slots) {
  1075. X        /* overflow of notes field, so
  1076. X         * add to last note field list
  1077. X         */
  1078. X        slotno = n_slots - 1;
  1079. X    }
  1080. X    add_to_slot(slotno, appt, FALSE);
  1081. X}
  1082. X
  1083. X/*
  1084. X * Fills in appointments for the day.  
  1085. X * The ".tmp.aptsXXXXX" file is filled out
  1086. X * with all the lines from the ".appointments" file 
  1087. X * which do not pertain to the current day.
  1088. X */
  1089. Xint
  1090. Xget_day_appts()
  1091. X{
  1092. X    FILE *apts, *temp_apts;
  1093. X    int slotno, n_arrows, i, j, k;
  1094. X    int read_stat, some_appt = 0;
  1095. X    int runl;
  1096. X    struct appt_entry appt;
  1097. X    struct appt_entry *nappt, *aptr;
  1098. X    char buf[MAX_STRLEN], *sptr;
  1099. X
  1100. X    if ((apts = fopen(apts_pathname, "r")) == NULL)
  1101. X        err_rpt("can't open appointments file", FATAL);
  1102. X
  1103. X    if (!read_only)
  1104. X            if ((temp_apts = fopen(tmpapts_pathname, "w")) == NULL)
  1105. X            err_rpt("can't open temp file for writing", FATAL);
  1106. X
  1107. X    for (i=0; i<n_slots; i++) {    /* init each slot */
  1108. X        slots[i].count = 0;
  1109. X        slots[i].cur_appt = NULL;
  1110. X        slots[i].first = NULL;
  1111. X        slots[i].active = 0;
  1112. X    }
  1113. X    First = current;
  1114. X    findex = 0;
  1115. X
  1116. X#ifndef NO_HOLIDAYS
  1117. X    /*
  1118. X     * First check to see if the user has selected any holiday
  1119. X     * options and add them in.
  1120. X     */
  1121. X    working(TRUE);
  1122. X    if (holiday_a) {
  1123. X        j = a_dates(holiday_a);
  1124. X        for (k=0; k<j; k++)
  1125. X            if (ymd2_compare(¤t, &a_appts[k]) == 0) {
  1126. X                some_appt |= (holiday_a == 1 ? SOME_MKNOTES : SOME_NOTES);
  1127. X                add_note(&a_appts[k]);
  1128. X            }
  1129. X    }
  1130. X    working(FALSE);
  1131. X    if (holiday_c) {
  1132. X        j = c_dates(holiday_c);
  1133. X        for (k=0; k<j; k++)
  1134. X            if (ymd2_compare(¤t, &c_appts[k]) == 0) {
  1135. X                some_appt |= (holiday_c == 1 ? SOME_MKNOTES : SOME_NOTES);
  1136. X                add_note(&c_appts[k]);
  1137. X            }
  1138. X    }
  1139. X    working(TRUE);
  1140. X    if (holiday_i) {
  1141. X        j = i_dates(holiday_i);
  1142. X        for (k=0; k<j; k++)
  1143. X            if (ymd2_compare(¤t, &i_appts[k]) == 0) {
  1144. X                some_appt |= (holiday_i == 1 ? SOME_MKNOTES : SOME_NOTES);
  1145. X                /* look for \n */
  1146. X                if ((sptr = index(i_appts[k].str, '\n')) != NULL) {
  1147. X                    appt = i_appts[k];
  1148. X                    /* two notes in one */
  1149. X                    strcpy(buf, appt.str);
  1150. X                    *sptr = '\0';
  1151. X                    add_note(&appt);
  1152. X                    /* now second half of string in the next note */
  1153. X                    strcpy(appt.str, &buf[(int)(sptr-appt.str)+1]);
  1154. X                    add_note(&appt);
  1155. X                } else
  1156. X                    add_note(&i_appts[k]);
  1157. X            }
  1158. X    }
  1159. X    working(FALSE);
  1160. X    if (holiday_j) {
  1161. X        j = j_dates(holiday_j);
  1162. X        for (k=0; k<j; k++)
  1163. X            if (ymd2_compare(¤t, &j_appts[k]) == 0) {
  1164. X                some_appt |= (holiday_j == 1 ? SOME_MKNOTES : SOME_NOTES);
  1165. X                add_note(&j_appts[k]);
  1166. X            }
  1167. X    }
  1168. X    working(TRUE);
  1169. X    if (holiday_s) {
  1170. X        j = s_dates(holiday_s);
  1171. X        for (k=0; k<j; k++)
  1172. X            if (ymd2_compare(¤t, &s_appts[k]) == 0) {
  1173. X                some_appt |= (holiday_s == 1 ? SOME_MKNOTES : SOME_NOTES);
  1174. X                add_note(&s_appts[k]);
  1175. X            }
  1176. X    }
  1177. X    working(FALSE);
  1178. X#endif
  1179. X            
  1180. X    /*
  1181. X     * now go thru the appointments file
  1182. X     */
  1183. X    while ((read_stat=get_aentry(apts, &appt, FALSE, FALSE, First.tm_mon+1)) != EOF) {
  1184. X        if (read_stat)
  1185. X            continue;    /* read error (ignore) */
  1186. X        if (appt.flags & A_COMMENT) {
  1187. X            if (put_aentry(temp_apts, &appt)) {
  1188. X                /* write error */
  1189. X                break;
  1190. X            }
  1191. X            continue;
  1192. X        }
  1193. X        current.tm_year = appt.year;
  1194. X        current.tm_mon = appt.month;
  1195. X        current.tm_mday = appt.day;
  1196. X        if (appt.flags & ALL_YEARS)
  1197. X            current.tm_year = First.tm_year;
  1198. X        if (appt.flags & ALL_MONTHS)
  1199. X            current.tm_mon = First.tm_mon;
  1200. X        if (appt.flags & ALL_DAYS)
  1201. X            current.tm_mday = First.tm_mday;
  1202. X        else if (appt.flags & EVERY_MON_FRI) {
  1203. X            if (First.tm_wday >= MON && First.tm_wday <= FRI)
  1204. X                current.tm_mday = First.tm_mday;
  1205. X            else
  1206. X                current.tm_mday = 0;
  1207. X        } else if (appt.flags & EVERY_SOMEDAY) {
  1208. X            if ((Pickday(appt.flags) == First.tm_wday)
  1209. X                && (chk_week(appt.repeat, First.tm_mday))) {
  1210. X                if (appt.flags & RUN) {
  1211. X                    runl = appt.runlength;
  1212. X                    find_date(&appt);
  1213. X                    while (ymd_compare(current, First) < 0 && --runl) {
  1214. X                        current.tm_mday += 7;
  1215. X                        find_date(&appt);
  1216. X                    }
  1217. X                } else
  1218. X                    current.tm_mday = First.tm_mday;
  1219. X            } else
  1220. X                current.tm_mday = 0;
  1221. X        } else if (appt.flags & REPEAT) {
  1222. X            if (appt.flags & RUN)
  1223. X                runl = appt.runlength;
  1224. X            else
  1225. X                runl = 1;
  1226. X            while (ymd_compare(current, First) < 0 && runl) {
  1227. X                if (appt.flags & RUN)
  1228. X                    --runl;
  1229. X                if (runl) {
  1230. X                    current.tm_mday += appt.repeat;
  1231. X                    fix_current_day();
  1232. X                }
  1233. X            }
  1234. X        }
  1235. X        if (ymd_compare(current, First) == 0) {
  1236. X            /* if it's for this day, fill in slot info */
  1237. X            if (appt.flags & A_NOTE) {
  1238. X                /* notes section */
  1239. X                add_note(&appt);
  1240. X                if (appt.flags & MARKED)
  1241. X                    /* marked note */
  1242. X                    some_appt |= SOME_MKNOTES;
  1243. X                else
  1244. X                    /* regular note */
  1245. X                    some_appt |= SOME_NOTES;
  1246. X            } else {
  1247. X                /* regular appointment */
  1248. X                slotno = (appt.hour-start_hour) * 2 + appt.minute / 30;
  1249. X                if (slotno < 0)
  1250. X                    slotno = 0;
  1251. X                if (slotno >= n_tslots)
  1252. X                    slotno = n_tslots - 1;
  1253. X                /* add this appt to the list of appts for the slot */
  1254. X                /* and update all the reference counts */
  1255. X                add_to_slot(slotno, &appt, FALSE);
  1256. X                some_appt |= SOME_APPTS;
  1257. X            }
  1258. X        } else if (appt.flags & LOOKAHEAD) {
  1259. X            /* This lookahead appt was not for today, so
  1260. X             * put it in the temp file.
  1261. X             */
  1262. X            if (put_aentry(temp_apts, &appt)) {
  1263. X                /* write error */
  1264. X                break;
  1265. X            }
  1266. X            if (appt.flags & EVERY_SOMEDAY) {
  1267. X                /* find next occurance of this appt */
  1268. X                /* starting from the current day */
  1269. X                current.tm_mday = First.tm_mday;
  1270. X                fix_current_day();
  1271. X                find_date(&appt); /* may modify current */
  1272. X            }
  1273. X            if (ymd_compare(current, First) > 0) {
  1274. X                /* this appt is happening in
  1275. X                 * the future, so remind us of it if
  1276. X                 * it is within the lookahead window.
  1277. X                 */
  1278. X                save_day = current;
  1279. X                current.tm_mday -= appt.lookahead;
  1280. X                fix_current_day();
  1281. X                if (ymd_compare(current, First) <=0) {
  1282. X                    /* save this one for the future popup window */
  1283. X                    if (findex > MAX_FUTURE_ENTRIES-1) {
  1284. X                        err_rpt("Too many future reminders", NON_FATAL);
  1285. X                        continue;
  1286. X                    }
  1287. X                    future[findex] = appt;
  1288. X                    /* fix up ymd */
  1289. X                    future[findex].year = save_day.tm_year;
  1290. X                    future[findex].month = save_day.tm_mon;
  1291. X                    future[findex].day = save_day.tm_mday;
  1292. X                    ++findex;
  1293. X                    some_appt |= SOME_FUTURES;
  1294. X                }
  1295. X            }
  1296. X                } else {     /* line is not for today */
  1297. X            /* copy it to temp file */
  1298. X            if (put_aentry(temp_apts, &appt)) {
  1299. X                /* write error */
  1300. X                break;
  1301. X            }
  1302. X        }
  1303. X        }
  1304. X    if (!read_only) {
  1305. X        if (ferror(temp_apts))
  1306. X            err_rpt("write on temp file failed", FATAL);
  1307. X            fclose(temp_apts);        
  1308. X    }
  1309. X        fclose(apts);             
  1310. X    current = First;
  1311. X    fix_current_day();
  1312. X    orphan_check();
  1313. X
  1314. X    return(some_appt);
  1315. X}
  1316. X
  1317. X
  1318. X/* check for match on weekly re-ocurring appts */
  1319. Xchk_week(repeat, curday)
  1320. Xint repeat, curday;
  1321. X{
  1322. X    int weeknr = 0;
  1323. X
  1324. X    if ((repeat & ALL_WEEKS) == ALL_WEEKS)
  1325. X        return(1);    /* every week */
  1326. X    if ((repeat & LAST_WEEK) && ((curday+7) > monthlength(current.tm_mon)))
  1327. X        return(1);    /* last week in month */
  1328. X
  1329. X    while (curday > 7) {
  1330. X        /* find which week this day is in */
  1331. X        curday -= 7;
  1332. X        weeknr++;
  1333. X    }
  1334. X    if (repeat & (0x1<<weeknr))
  1335. X        return(1);
  1336. X    
  1337. X    return(0);    /* no match */
  1338. X}
  1339. X
  1340. X
  1341. X/*
  1342. X * get date of next occurrance of a weekly repeated appt
  1343. X * (it may bridge into next week, month or year)
  1344. X */
  1345. Xfind_date(appt)
  1346. Xstruct appt_entry *appt;
  1347. X{
  1348. X    struct tm save;
  1349. X    int runl;
  1350. X
  1351. X    save = current;
  1352. X    fix_current_day();
  1353. X    /* set current to match dow of repeated appt */
  1354. X    if (appt->flags & EVERY_MON_FRI) {
  1355. X        if (current.tm_wday == SUN)
  1356. X            current.tm_mday++;
  1357. X        else if (current.tm_wday == SAT)
  1358. X            current.tm_mday += 2;
  1359. X    } else 
  1360. X        current.tm_mday += Pickday(appt->flags) - current.tm_wday;
  1361. X    fix_current_day();
  1362. X    if (ymd_compare(current, save) < 0) {
  1363. X        /* already happened, so start looking next week */
  1364. X        current.tm_mday += 7;
  1365. X        fix_current_day();
  1366. X    }
  1367. X    /* search for first matching week */
  1368. X    while (!chk_week(appt->repeat, current.tm_mday)) {
  1369. X        current.tm_mday += 7;
  1370. X        fix_current_day();
  1371. X    }
  1372. X    /* now check to make sure this is legal, i.e. there
  1373. X     * were no month or year restrictions
  1374. X     */
  1375. X    if (!(appt->flags & RUN) && ((!(appt->flags & ALL_YEARS) && current.tm_year != save.tm_year)
  1376. X       || (!(appt->flags & ALL_MONTHS) && current.tm_mon != save.tm_mon)))
  1377. X        /* invalid date, due to month or year wrap */
  1378. X        current = save;
  1379. X}
  1380. X
  1381. X/*
  1382. X * orphan_check() - check each slot for orphan appointments. Orphans
  1383. X * are a deleted recurring appointment where it is deleted on a
  1384. X * specific date and the original appointment no longer exists.
  1385. X */
  1386. Xorphan_check()
  1387. X{
  1388. X    int i, n_arrows;
  1389. X    struct appt_entry *aptr, *optr;
  1390. X
  1391. X    for (i=0; i<n_slots; i++) {
  1392. X        while (slots[i].first != NULL) {
  1393. X            optr = slots[i].first;
  1394. X            if (chk_deleted(&slots[i], optr) == -1) {
  1395. X                /* just adjust the counts */
  1396. X                n_arrows = optr->arrows;
  1397. X                while (n_arrows >= 0)
  1398. X                    slots[i+(n_arrows--)].count++;
  1399. X                slots[i].active++;
  1400. X                if (optr->next) {
  1401. X                    if (slots[i].cur_appt == slots[i].first)
  1402. X                        slots[i].cur_appt = slots[i].first->next;
  1403. X                    slots[i].first = slots[i].first->next;
  1404. X                } else {
  1405. X                    /* last one */
  1406. X                    if (slots[i].cur_appt == slots[i].first)
  1407. X                        slots[i].cur_appt = NULL;
  1408. X                    slots[i].first = NULL;
  1409. X                    slots[i].active = 0;
  1410. X                }
  1411. X                free(optr);
  1412. X                new_entry = 1;
  1413. X            } else {
  1414. X                while (aptr = optr->next) {
  1415. X                    if (chk_deleted(&slots[i], aptr) == -1) {
  1416. X                        /* just adjust the counts */
  1417. X                        n_arrows = aptr->arrows;
  1418. X                        while (n_arrows >= 0)
  1419. X                            slots[i+(n_arrows--)].count++;
  1420. X                        slots[i].active++;
  1421. X                        optr->next = aptr->next;
  1422. X                        if (slots[i].cur_appt == aptr)
  1423. X                            slots[i].cur_appt = aptr->next;
  1424. X                        free(aptr);
  1425. X                        new_entry = 1;
  1426. X                    } else {
  1427. X                        optr = aptr;
  1428. X                    }
  1429. X                }
  1430. X                break;
  1431. X            }
  1432. X        }
  1433. X        if (chk_deleted(&slots[i], slots[i].cur_appt)) {
  1434. X            next_appt(i, FALSE);
  1435. X            if (slots[i].cur_appt == NULL)
  1436. X                /* only deleted appts, so reset to first */
  1437. X                slots[i].cur_appt = slots[i].first;
  1438. X        }
  1439. X    }
  1440. X}
  1441. X
  1442. X/* check to see if appt is deleted */
  1443. Xint
  1444. Xchk_deleted(slptr, aptr)
  1445. Xstruct dayslot *slptr;
  1446. Xstruct appt_entry *aptr;
  1447. X{
  1448. X    int found = 0;
  1449. X    struct appt_entry *optr;
  1450. X
  1451. X    if (slptr->first == NULL || aptr == NULL)
  1452. X        return(0);
  1453. X    if (aptr->flags & DELETED) {
  1454. X        /* run through the list and look for a matching
  1455. X         * repeating non-deleted entry. If we don't find one,
  1456. X         * this appt is a deleted orphan.
  1457. X         */
  1458. X        for (optr=slptr->first; optr; optr=optr->next)
  1459. X            if (!(optr->flags & DELETED) && Repeating(optr->flags))
  1460. X                /* now see if the current one matches */
  1461. X                if (!strcmp(optr->str, aptr->str))
  1462. X                    return(1);
  1463. X        return(-1);  /* orphan */
  1464. X    }
  1465. X    if (Repeating(aptr->flags)) {
  1466. X        /* run through the list to see if there are any deleted */
  1467. X        for (optr=slptr->first; optr; optr=optr->next)
  1468. X            if (optr->flags & DELETED) {
  1469. X                /* now see if the current one matches */
  1470. X                if (!strcmp(optr->str, aptr->str))
  1471. X                    return(1);
  1472. X            }
  1473. X    }
  1474. X    
  1475. X    return(0);
  1476. X}
  1477. X
  1478. X/*
  1479. X * When timer has expired check to see if we are close to an
  1480. X * appointment. If so, switch to the other icon so we have a
  1481. X * visual indication and beep the console (if enabled).
  1482. X */
  1483. Xcheck_calendar()
  1484. X{
  1485. X    int appt_pending = 0;     /* no appointments pending */
  1486. X    int slotno = 0;     /* start with first timeslot */
  1487. X    int smin, tmin;
  1488. X    int sno, save_ro;
  1489. X    static int echoed_sno = -1;
  1490. X    static int new_day = 0;
  1491. X    FILE *console;
  1492. X    struct appt_entry *aptr;
  1493. X    struct tm Saveday;
  1494. X    char *getenv();
  1495. X    static time_t lastmod = (time_t)0;
  1496. X    struct stat stbuf;
  1497. X#ifndef CALENCHECK
  1498. X    char msgfile[128];
  1499. X    int some_appts = 0;    /* no appointments today */
  1500. X    static int icon_in_use = STD_ICON;
  1501. X    Icon cur_icon;
  1502. X    FILE *msgf;
  1503. X#endif
  1504. X
  1505. X#ifndef CALENCHECK
  1506. X    if (locked)    /* can't change yet */
  1507. X        return;
  1508. X    lock_cursors();
  1509. X    locked++;    /* make it unique to us */
  1510. X    strcpy(msgfile, getenv("HOME"));
  1511. X    strcat(msgfile, "/.msgfile");
  1512. X#endif
  1513. X
  1514. X    sno = echoed_sno;    /* assume no console echo */
  1515. X    get_today();
  1516. X    stat(apts_pathname, &stbuf);
  1517. X    Saveday = current;
  1518. X    /*
  1519. X     * Check to see if we're not displaying today.
  1520. X     * (Or in the case of "calencheck" if the appointments
  1521. X     * file has been modified.) If so, we need to update our
  1522. X     * slot information.
  1523. X     */
  1524. X#ifndef CALENCHECK
  1525. X    if ((int)window_get(frame, FRAME_CLOSED) && ymd_compare(closedate, today) != 0)
  1526. X        new_day++;
  1527. X#endif
  1528. X    if (ymd_compare(current, today) != 0 || new_day) {
  1529. X        if (day_is_open)
  1530. X            close_day();
  1531. X        current = today;
  1532. X#ifdef CALENCHECK
  1533. X        new_day++;
  1534. X#endif
  1535. X    }
  1536. X    if (stbuf.st_mtime > lastmod) {
  1537. X        lastmod = stbuf.st_mtime;
  1538. X        day_is_open = FALSE;    /* force reading appts file */
  1539. X        sno = echoed_sno = -1;
  1540. X    }
  1541. X    if (day_is_open) {
  1542. X        /* slot info is current */
  1543. X#ifndef CALENCHECK
  1544. X        unlock_cursors();
  1545. X#endif
  1546. X    } else {
  1547. X#ifdef CALENCHECK
  1548. X        (void)get_day_appts();
  1549. X#else
  1550. X        save_ro = read_only;
  1551. X        read_only = 1;    /* force read only mode */
  1552. X        err2console(TRUE);
  1553. X        (void)get_day_appts();
  1554. X        err2console(FALSE);
  1555. X#endif
  1556. X        day_is_open = TRUE;
  1557. X        read_only = save_ro;
  1558. X        if (new_day)
  1559. X            sno = echoed_sno = -1;
  1560. X    }
  1561. X
  1562. X    slotno = (today.tm_hour - start_hour)*2 + today.tm_min/30;
  1563. X    if (slotno < 0)
  1564. X        slotno = 0;
  1565. X    /* our current time (minutes past midnight) */
  1566. X    tmin = today.tm_hour * 60 + today.tm_min;
  1567. X    if (slots[slotno].count > 0 && slotno < n_tslots)
  1568. X        /* something going on now */
  1569. X        appt_pending++;
  1570. X    while (slotno < n_tslots) {
  1571. X        if (slots[slotno].count > 0) {
  1572. X            /* convert slotno back to time difference */
  1573. X            smin = start_hour * 60 + slotno * 30 - tmin;
  1574. X            if (smin < 0)
  1575. X                smin = 0;
  1576. X            if (slots[slotno].active) {
  1577. X                /* get all valid appts at this time */
  1578. X                for (aptr=slots[slotno].first; aptr;
  1579. X                    aptr=aptr->next)
  1580. X                    if (!chk_deleted(&slots[slotno], aptr)
  1581. X                        && aptr->warn
  1582. X                        && (smin <= aptr->warn)) {
  1583. X                        sno = slotno;
  1584. X                        appt_pending++;
  1585. X                        break;
  1586. X                    }
  1587. X                if (sno > echoed_sno)
  1588. X                    break;
  1589. X            }
  1590. X        }
  1591. X        slotno++;
  1592. X    }
  1593. X    if (!appt_pending) {
  1594. X#ifndef CALENCHECK
  1595. X        /*
  1596. X         * Is there anything happening today (optionally
  1597. X         * including memos)?
  1598. X         * Don't care about things that happened before now
  1599. X         * so start looking at <slotno>, which is set to
  1600. X         * reflect the current hour (or 0 if before start_hour).
  1601. X         */
  1602. X        slotno = (today.tm_hour - start_hour)*2 + today.tm_min/30;
  1603. X        if (slotno < 0)
  1604. X            slotno = 0;
  1605. X        /*
  1606. X         * appt_check_limit is typically either "n_tslots"
  1607. X         * or "n_slots" depending on whether we include the
  1608. X         * notes section when indicating that we still have
  1609. X         * appts today.
  1610. X         */
  1611. X        while (slotno < appt_check_limit)
  1612. X            if (slots[slotno++].count) {
  1613. X                some_appts++;
  1614. X                break;
  1615. X            }
  1616. X        /* maybe change the icon */
  1617. X        if ((some_appts && (icon_in_use != STD_ICON)) ||
  1618. X           (!some_appts && (icon_in_use != NA_ICON))) {
  1619. X            window_set(frame,
  1620. X                FRAME_ICON, (some_appts?
  1621. X                icon : na_icon),
  1622. X                0);
  1623. X            icon_in_use = some_appts ? STD_ICON : NA_ICON;
  1624. X        }
  1625. X        /* clean out the ~/.msgfile file */
  1626. X        if (beep && ((msgf = fopen(msgfile, "w")) != NULL)) {
  1627. X            fprintf(msgf, "I'm out running around.");
  1628. X            fclose(msgf);
  1629. X        }
  1630. X#endif
  1631. X    } else {
  1632. X         /* notify the user via the console (once) ... */
  1633. X#ifdef CALENCHECK
  1634. X        if (sno > echoed_sno) {
  1635. X            echoed_sno = sno;
  1636. X            /* get all valid appts at this time */
  1637. X            for (aptr=slots[sno].first; aptr; aptr=aptr->next)
  1638. X                if (!chk_deleted(&slots[sno], aptr)) {
  1639. X                    if (getenv("WINDOW_PARENT") != NULL
  1640. X                        && (console = fopen("/dev/console", "w")) != NULL) {
  1641. X                        fprintf(console, "<< %s >> %s\n",
  1642. X                            progname, aptr->str);
  1643. X                        fclose(console);
  1644. X                    } else {
  1645. X                        fprintf(stderr, "\007\007<< %s >> %s\n",
  1646. X                            progname, aptr->str);
  1647. X                    }
  1648. X                }
  1649. X        }
  1650. X#else
  1651. X        if ((beep || beep_open) && sno > echoed_sno) {
  1652. X            echoed_sno = sno;
  1653. X            window_bell(frame);
  1654. X            if (beep_open) {
  1655. X                olddate = Saveday = today;
  1656. X                mainsw_state = DISPLAYING_DAY;
  1657. X                window_set(frame, FRAME_CLOSED, FALSE, 0);
  1658. X            }
  1659. X            if (beep)
  1660. X                if ((console = fopen("/dev/console", "w")) != NULL) {
  1661. X                    /* get all valid appts at this time */
  1662. X                    for (aptr=slots[sno].first; aptr;
  1663. X                        aptr=aptr->next)
  1664. X                        if (!chk_deleted(&slots[sno], aptr))
  1665. X                            fprintf(console, "<< %s >> %s\n", progname, aptr->str);
  1666. X                    fclose(console);
  1667. X                }
  1668. X            /*
  1669. X             * also put a copy in ~/.msgfile, in case
  1670. X             * nlock(1) is running
  1671. X             */
  1672. X            if ((msgf = fopen(msgfile, "w")) != NULL) {
  1673. X                fprintf(msgf, "%s", slots[sno].cur_appt->str);
  1674. X                fclose(msgf);
  1675. X            }
  1676. X        }
  1677. X         /* ... and change the icon */
  1678. X        if (icon_in_use != REV_ICON) {
  1679. X            window_set(frame,
  1680. X                FRAME_ICON, rev_icon,
  1681. X                0);
  1682. X            icon_in_use = REV_ICON;
  1683. X        }
  1684. X#endif
  1685. X    }
  1686. X#ifdef CALENCHECK
  1687. X    if (new_day)
  1688. X        Saveday = today;
  1689. X#else
  1690. X    if (new_day && (int)window_get(frame, FRAME_CLOSED)) {
  1691. X        /* update times so that it opens on today */
  1692. X        closedate = olddate = Saveday = today;
  1693. X        /* update date field of the icons */
  1694. X        sprintf(datestr_day, "%d", today.tm_mday);
  1695. X        /* replace the date */
  1696. X        where.pr = ic_pr;
  1697. X        where.pos.x = 13;
  1698. X        where.pos.y = 49 + 5;
  1699. X        pr_rop(where.pr, 14, 47, 10, 8, PIX_CLR, NULL, 0, 0);
  1700. X        pr_rop(where.pr, 40, 47, 16, 8, PIX_CLR, NULL, 0, 0);
  1701. X        pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_day);
  1702. X        where.pr = na_ic_pr;
  1703. X        pr_rop(where.pr, 14, 47, 10, 8, PIX_CLR, NULL, 0, 0);
  1704. X        pr_rop(where.pr, 40, 47, 16, 8, PIX_CLR, NULL, 0, 0);
  1705. X        pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_day);
  1706. X        where.pr = rev_ic_pr;
  1707. X        pr_rop(where.pr, 14, 47, 10, 8, PIX_SET, NULL, 0, 0);
  1708. X        pr_rop(where.pr, 40, 47, 16, 8, PIX_SET, NULL, 0, 0);
  1709. X        pf_ttext(where, PIX_SRC, sfont, datestr_day);
  1710. X        where.pos.x = 39;
  1711. X        where.pr = ic_pr;
  1712. X        pf_ttext(where, PIX_NOT(PIX_SRC), sfont, smonthnames[today.tm_mon]);
  1713. X        where.pr = na_ic_pr;
  1714. X        pf_ttext(where, PIX_NOT(PIX_SRC), sfont, smonthnames[today.tm_mon]);
  1715. X        where.pr = rev_ic_pr;
  1716. X        pf_ttext(where, PIX_SRC, sfont, smonthnames[today.tm_mon]);
  1717. X        icon_set(icon, ICON_IMAGE, ic_pr, 0);
  1718. X        icon_set(rev_icon, ICON_IMAGE, rev_ic_pr, 0);
  1719. X        icon_set(na_icon, ICON_IMAGE, na_ic_pr, 0);
  1720. X        switch (icon_in_use) {
  1721. X            case STD_ICON:
  1722. X                window_set(frame, FRAME_ICON, icon, 0);
  1723. X                break;
  1724. X            case REV_ICON:
  1725. X                window_set(frame, FRAME_ICON, rev_icon, 0);
  1726. X                break;
  1727. X            case NA_ICON:
  1728. X                window_set(frame, FRAME_ICON, na_icon, 0);
  1729. X                break;
  1730. X        }
  1731. X        new_day = 0;
  1732. X        show_future = 1;    /* show future appts again */
  1733. X    }
  1734. X#endif
  1735. X#ifndef CALENCHECK
  1736. X    current = Saveday;
  1737. X    err2console(TRUE);
  1738. X    (void)get_day_appts();
  1739. X    err2console(FALSE);
  1740. X    if (locked == 2)
  1741. X        unlock_cursors();
  1742. X#endif
  1743. X}
  1744. X
  1745. Xdo_files(window_prompt)
  1746. Xint window_prompt;
  1747. X{
  1748. X    char *slash, *default_ptr, *envptr;
  1749. X    char buff[80];
  1750. X    int to_slash, getpid(), fd, errflag, numask;
  1751. X    struct passwd *pw;
  1752. X    struct stat statbuf;
  1753. X    FILE *appts;
  1754. X    char *strcpy(), *rindex(), *getenv();
  1755. X
  1756. X    /* the tmp file */
  1757. X    sprintf(tmpapts_pathname, "/tmp/appts%d", getpid());
  1758. X    if (otherfile) {
  1759. X        strcpy(apts_pathname, othername);
  1760. X        if ((slash = rindex(apts_pathname, '/')) != NULL) {
  1761. X            to_slash = slash - apts_pathname;
  1762. X            strncpy(apts_dir, apts_pathname, to_slash);
  1763. X            apts_dir[to_slash] = '\0';
  1764. X        } else {
  1765. X            strcpy(apts_dir, ".");
  1766. X        }
  1767. X    } else {
  1768. X#ifndef NO_DEFAULTS
  1769. X        if ((default_ptr = defaults_get_string("/CalenTool/Appts", NULL, 0)) != NULL) {
  1770. X            if ((slash = rindex(default_ptr, '/')) != NULL) {
  1771. X                to_slash = slash - default_ptr;
  1772. X                strncpy(apts_dir, default_ptr, to_slash);
  1773. X                apts_dir[to_slash] = '\0';
  1774. X            } else {
  1775. X                strcpy(apts_dir, ".");
  1776. X            }
  1777. X        } else
  1778. X#endif
  1779. X        if ((envptr = getenv("CALENTOOL_DIR")) != NULL) {   
  1780. X            strcpy(apts_dir, envptr);
  1781. X#ifndef CALENCHECK
  1782. X        } else if (mailto) {
  1783. X            if ((pw = getpwnam(mailto)) == NULL)
  1784. X                /* no entry */
  1785. X                exit(1);
  1786. X            envptr = pw->pw_dir; /* home directory */
  1787. X            strcpy(apts_dir, envptr);
  1788. X#endif
  1789. X        } else if ((envptr = getenv("HOME")) != NULL) {   
  1790. X            strcpy(apts_dir, envptr);
  1791. X        } else {   
  1792. X            apts_dir[0] = '\0';
  1793. X        }
  1794. X        if (*apts_dir) {
  1795. X            /* prepend directory on pathnames */
  1796. X            sprintf(apts_pathname, "%s/.appointments", apts_dir);
  1797. X        } else {
  1798. X            /* use current directory */
  1799. X            strcpy(apts_pathname, ".appointments");
  1800. X        }
  1801. X    }
  1802. X    
  1803. X    /* directory for date/event data files */
  1804. X#ifndef NO_DEFAULTS
  1805. X    if ((default_ptr = defaults_get_string("/CalenTool/LibDir", NULL, 0)) != NULL)
  1806. X        strcpy(lib_dir, default_ptr);
  1807. X    else
  1808. X#endif
  1809. X        strcpy(lib_dir, DATELIB_DIR);
  1810. X
  1811. X    errflag = 0;
  1812. X    if (access(apts_pathname, R_OK) == -1) {
  1813. X#ifndef CALENCHECK
  1814. X        if (window_prompt) {
  1815. X            fprintf(stderr, "nonexistant file\n");
  1816. X            sprintf(buff, "Cannot access calendar file %s - create?", apts_pathname);
  1817. X            create_prompt_frame(buff, TRUE);
  1818. X            if ((int)window_loop(prompt_frame) == 0) {
  1819. X                /* try to create the file */
  1820. X                fprintf(stderr, "creating file\n");
  1821. X                if ((fd=open(apts_pathname, O_CREAT|O_RDWR, 0644)) <= 0) {
  1822. X                    perror(apts_pathname);
  1823. X                    errflag = 1;
  1824. X                    fprintf(stderr, "..error\n");
  1825. X                } else {
  1826. X                    if (write(fd, HEADER, sizeof(HEADER)) != sizeof(HEADER)) {
  1827. X                        perror("writing header");
  1828. X                        errflag = 1;
  1829. X                    }
  1830. X                    close(fd);
  1831. X                    fprintf(stderr, "..wrote header\n");
  1832. X                    one_based = 1;
  1833. X                }
  1834. X            } else {
  1835. X                fprintf(stderr, "window_ret != 0\n");
  1836. X                errflag = 1;
  1837. X            }
  1838. X            window_set(prompt_frame, WIN_SHOW, FALSE, 0);
  1839. X            if (errflag)
  1840. X                return(1);
  1841. X        } else {
  1842. X#endif
  1843. X            fprintf(stderr, "Cannot access calendar file %s - create? ", apts_pathname);
  1844. X            fgets(buff, 80, stdin);
  1845. X            if (buff[0] == 'y' || buff[0] == 'Y') {
  1846. X                if ((fd=open(apts_pathname, O_CREAT|O_RDWR, 0644)) <= 0) {
  1847. X                    perror(apts_pathname);
  1848. X                    return(1);
  1849. X                } else {
  1850. X                    if (write(fd, HEADER, sizeof(HEADER)) != sizeof(HEADER)) {
  1851. X                        perror("writing header");
  1852. X                        close(fd);
  1853. X                        return(1);
  1854. X                    }
  1855. X                    close(fd);
  1856. X                    one_based = 1;
  1857. X                }
  1858. X            } else
  1859. X                return(1);
  1860. X        }
  1861. X#ifndef CALENCHECK
  1862. X    }
  1863. X    if (!read_only)
  1864. X        if (access(apts_pathname, W_OK) == -1)
  1865. X            read_only = 1;
  1866. X    /*
  1867. X     * set permissions on tmp file based on .appointments file
  1868. X     * with the expception that we need at least write permission
  1869. X     * for the owner.
  1870. X     */
  1871. X    (void)stat(apts_pathname, &statbuf);
  1872. X    numask = ~statbuf.st_mode & 0077;  /* yes, this is octal 77 */
  1873. X    (void)umask(numask);
  1874. X
  1875. X    /* update base frame label, if the tool is running */
  1876. X    if (frame) {
  1877. X        strcpy(t_title, version());
  1878. X        if (read_only)
  1879. X            strcat(t_title, " [Read Only]");
  1880. X        strcat(t_title, "  -  ");
  1881. X        strcat(t_title, apts_pathname);
  1882. X        window_set(frame, FRAME_LABEL, t_title, 0);
  1883. X    }
  1884. X#endif
  1885. X
  1886. X    /* check first line of appts file to see if it is the new style */
  1887. X    if ((appts = fopen(apts_pathname, "r")) != NULL) {
  1888. X        fgets(buff, 80, appts);
  1889. X        fclose(appts);
  1890. X        if (!strcmp(buff, OHEADER) || !strncmp(buff, HEADER, 18)) {
  1891. X            version2 = 1;
  1892. X            one_based = 1;
  1893. X        }
  1894. X#ifdef CALENCHECK
  1895. X        else
  1896. X            err_rpt("wrong version appointments file format", FATAL);
  1897. X#endif
  1898. X    }
  1899. X
  1900. X#ifndef CALENCHECK
  1901. X    /* Convert from old format to new. There may some appts files
  1902. X     * that are one-based, but are still old style. These are
  1903. X     * also handled. (Note: for old-style one-based appts files
  1904. X     * the user MUST start calentool with the -z flag.)
  1905. X     */
  1906. X     if (!version2)
  1907. X        ver1to2();
  1908. X#endif
  1909. X    
  1910. X    return(0);
  1911. X}
  1912. X
  1913. END_OF_FILE
  1914. if test 29124 -ne `wc -c <'common.c'`; then
  1915.     echo shar: \"'common.c'\" unpacked with wrong size!
  1916. fi
  1917. # end of 'common.c'
  1918. fi
  1919. echo shar: End of archive 17 \(of 23\).
  1920. cp /dev/null ark17isdone
  1921. MISSING=""
  1922. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ; do
  1923.     if test ! -f ark${I}isdone ; then
  1924.     MISSING="${MISSING} ${I}"
  1925.     fi
  1926. done
  1927. if test "${MISSING}" = "" ; then
  1928.     echo You have unpacked all 23 archives.
  1929.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1930. else
  1931.     echo You still need to unpack the following archives:
  1932.     echo "        " ${MISSING}
  1933. fi
  1934. ##  End of shell archive.
  1935. exit 0
  1936.  
  1937. exit 0 # Just in case...
  1938. -- 
  1939. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1940. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1941. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1942. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1943.